#!/usr/bin/python
# -*- encoding: UTF-8 -*-

from __future__ import print_function

import gtk
import time
import random

import ascensores

from gtkmvc import Controller
from gtkmvc.adapters import Adapter

class ControladorEdificio(Controller):
    def __init__(self, model, view, ascensores):
        Controller.__init__(self, model, view)

        self.ascensores = ascensores

        for m, v, c in self.ascensores:
            c.asignar_edificio(self)

    def terminar(self, widget):
        self.model.terminar()
        gtk.main_quit(widget)

    def register_view(self, view):
        view['main_window'].connect('destroy', self.terminar)

    @Controller.observe("pedidos", after=True)
    def update_pedidos(self, model, prop_name, info):
        if prop_name == "pedidos" and info["method_name"] == "append":
            if self.model.pedidos:
                asignado = None
                piso = self.model.pedidos.pop()
                cercania = []
                for a in self.model.ascensores:
                    cercania.append( (abs(a.posicion-piso), a) )
                cercania.sort()
                for dist, a in cercania:
                    asignar = False
                    if not a.is_moviendose() and not a.pedidos:
                        asignar = True
                    else:
                        peso_ok = a.peso + 75 < a.capacidad
                        if a.movimiento == "subiendo" and piso > int(a.posicion)+2:
                            asignar = True
                        elif a.movimiento == "bajando" and piso < int(a.posicion)-2:
                            asignar = True
                    if asignar:
                        if self.model._asignar_ascensor(a, piso):
                            asignado = a
                        break
                if asignado is None:
                    self.model.pedidos.insert(0,piso)
#                print (piso, asignado)

    def inyectarPersona(self, nombre = None, inicio = None, fin = None, peso = 85):
        while inicio is None or abs(fin-inicio) <= 2:
            inicio = random.randint(0,10)
        while fin is None or abs(fin-inicio) <= 2:
            fin = random.randint(0,10)

        p = ascensores.Persona(nombre, self.model, inicio=inicio, destino=fin, peso=peso, delay=2)
        print (p)
        print ("{0}: Inyectando persona {1} al sistema.",self.model.nombre, nombre)
        self.model.registrar_persona(p)
        p.start()

    pass # ControladorEdificio

class ControladorAscensor(Controller):
    def __init__(self, model, view):    
        Controller.__init__(self, model, view)

        self.anterior = { "movimiento":"detenido", "destino":0, "pedidos":"[]" , "capacidad":0 }
        self.edificio = None

    def asignar_edificio(self, edificio):
        self.edificio = edificio

    def register_view(self, view):
        Controller.register_view(self,view)

        for b in view["botonera"].get_children():
            if isinstance(b, gtk.Button):
                label = b.get_label()
                if not label is None:
                    try:
                        int(label)
                        b.connect("pressed", self.on_button_piso)
                    except ValueError:
                        pass

    def on_button_piso(self, button):
        piso = None
        try:
            piso = int(button.get_label())
        except ValueError:
            pass

        if not piso is None:
            fin = None
            while fin is None or abs(fin-piso) <= 2:
                fin = random.randint(1,10)
                peso = random.randint(85,110)
#            self.edificio.inyectarPersona(nombre = "P{0}a{1}".format(piso,fin), inicio=piso, fin=fin, peso=peso)

    def update(self, model, prop_name, info):
        if not self.view is None:
            self.view.update(prop_name,info['new'])

            if prop_name != "movimiento":
                if model.movimiento != self.anterior["movimiento"]:
                    self.view.update("movimiento",model.movimiento)
                    self.anterior["movimiento"] = model.movimiento
            if prop_name != "destino":
                if model.destino != self.anterior["destino"]:
                    self.view.update("destino",model.destino)
                    self.anterior["destino"] = model.destino
            if prop_name != "pedidos":
                if str(model.pedidos) != self.anterior["pedidos"]:
                    self.view.update("pedidos",str(model.pedidos))
                    self.anterior["pedidos"] = str(model.pedidos)
#            if prop_name != "peso":
#                self.update_peso(model,"peso",model.peso)
#            if prop_name != "capacidad":
#                if str(model.capacidad) != self.anterior["capacidad"]:
#                    self.view.update("capacidad",model.capacidad)
#                    self.anterior["capacidad"] = model.capacidad

    @Controller.observe("posicion", assign=True)
    def update_posicion(self, model, prop_name, info):
        self.update(model, prop_name, info)

    @Controller.observe("luces", assign=True)
    def update_luces(self, model, prop_name, info):
        self.view.update_luces(model.luces)

    @Controller.observe("ventilacion", assign=True)
    def update_ventilacion(self, model, prop_name, info):
        self.view.update_ventilacion(model.ventilacion)
    
    @Controller.observe("peso", assign=True)
    def update_peso(self, model, prop_name, info):
        self.view.update_peso(model.peso);
        # Regla 3
        if model.peso > model.capacidad:
            # 3. Si el ascensor esta muy cargado, encender alarma e inhibir.
            self.view.update_alarma_peso(True)
            model.movimiento = "inhibido"
            # Solo puede salir de este estado si el peso cae y la alarma se desactiva.
        else:
            self.view.update_alarma_peso(False)
            model.movimiento = "detenido"

        # Reglas 1 y 2: 
        if model.peso > 0:
            # 2. Si el ascensor no esta vacio; encender ventilacion y luces.
            model.luces = True
            model.ventilacion = True
        else:
            # 1. Si el ascensor esta vacio; apagar ventilacion y luces.
            model.luces = False
            model.ventilacion = False

    @Controller.observe("capacidad", assign=True)
    def update_capacidad(self, model, prop_name, info):
        self.view.update_capacidad(info['new']);

    @Controller.observe("movimiento", assign=True)
    def update_movimiento(self, model, prop_name, info):
        self.update(model, prop_name, info)

    @Controller.observe("velocidad", assign=True)
    def update_velocidad(self, model, prop_name, info):
        self.view.update("velocidad",model.velocidad)

    @Controller.observe("destino", assign=True)
    def update_destino(self, model, prop_name, info):
        self.update(model, prop_name, info)

    @Controller.observe("pedidos", assign=True)
    def update_pedidos(self, model, prop_name, info):
        self.update(model, prop_name, info)

    @Controller.observe("puerta_abierta", assign=True)
    def update_puerta_abierta(self, model, prop_name, info):
        self.update(model, prop_name, info)

    pass # ControladorAscensor

